package com.test.pdproject.config.shrio;

import com.test.pdproject.auth.MyShiroRealm;
import com.test.pdproject.filter.MyShiroFilterFactoryBean;
import org.apache.log4j.Logger;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @ClassName lisaisai
 * @Descirption
 * Shiro 配置  Apache Shiro 核心
 * 通过Filter 来实现，就好像SpringMvc 通过DispachServlet 来主控制一样。
 * 既然是使用 Filter 一般也就能猜到，是通过URL规则来进行过滤和权限校验，所以我们需要定义一系列关于URL的规则和访问权限。
 * @Author Administrator
 * @Date 2018/9/17 12:46
 * @Version 1.0
 **/
@Configuration
@EnableTransactionManagement
public class ShiroConfiguration {
    private final Logger logger = Logger.getLogger(ShiroConfiguration.class);

    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，因为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     * <p>
     * Filter Chain定义说明
     * 1、一个URL可以配置多个Filter，使用逗号分隔
     * 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如perms，roles
     */
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager ehcacheManager = new EhCacheManager();
        ehcacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
        return ehcacheManager;


    }

    /**配置shiro仓库*/
    @Bean(name = "myShiroRealm")
    public MyShiroRealm myShiroRealm(EhCacheManager ehCacheManager) {
        MyShiroRealm realm = new MyShiroRealm();
        realm.setCacheManager(ehCacheManager);
        return realm;
    }

    /**把shiro生命周期交给spring boot管理*/
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    /** DefaultAdvisorAutoProxyCreator实现Spring自动代理*/
     @Bean
     public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
         DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
         creator.setProxyTargetClass(true);
         return creator;
     }

    /**权限认证信息*/
      @Bean(name = "securityManager")
      public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm) {
          System.out.println("shiro --> >>>>>>>>> >-->  启动");
          DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
          //设置realm
          securityManager.setRealm(realm);
          securityManager.setCacheManager(getEhCacheManager());
          return securityManager;
      }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    //shiro核心拦截器
     @Bean(name = "shiroFilter")
     public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
         ShiroFilterFactoryBean factoryBean = new MyShiroFilterFactoryBean();
         factoryBean.setSecurityManager(securityManager);
         // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
         factoryBean.setLoginUrl("/login");
         // 登录成功后要跳转的连接
         factoryBean.setSuccessUrl("/welcome");
         factoryBean.setUnauthorizedUrl("/403");
         loadShiroFilterChain(factoryBean);
         logger.info("shiro拦截器工厂类注入成功");
         return factoryBean;
     }
    //加载ShiroFilter权限控制规则
    private void loadShiroFilterChain(ShiroFilterFactoryBean factoryBean) {
        /**下面这些规则配置最好配置到配置文件中*/
        Map<String, String> filterChainMap = new LinkedHashMap<String, String>();
        // authc：该过滤器下的页面必须验证后才能访问，它是Shiro内置的一个拦截器
        // anon：它对应的过滤器里面是空的,什么都没做,可以理解为不拦截
        //authc:所有url都必须认证通过才可以访问; anon:所有url都可以匿名访问
        filterChainMap.put("/user/tologin", "anon");
        filterChainMap.put("/user/welcome", "anon");
        filterChainMap.put("/user/login", "anon");
        filterChainMap.put("/dubbo/*", "anon");
        filterChainMap.put("/error", "anon");
        filterChainMap.put("/tUser/insert", "anon");
        filterChainMap.put("/**", "authc");

        factoryBean.setFilterChainDefinitionMap(filterChainMap);
    }
}